package com.wjwframework.jfinal.interceptor;

import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.Prop;
import com.jfinal.plugin.activerecord.Record;
import com.wjw.utils.DateUtil;
import com.wjw.utils.IP;
import com.wjw.utils.mail.MailSendHelper;
import com.wjwframework.jfinal.vo.Response;

/**
 * @className ExceptionInterceptor
 * @description 异常拦截器
 * @author wjw
 * @cTime 2016年3月19日下午1:41:20
 */
public class ExceptionInterceptor implements Interceptor{

	protected Prop prop ;
	
	public Logger log=LoggerFactory.getLogger(getClass());
	
	public ExceptionInterceptor() {
		// TODO Auto-generated constructor stub
	}
	public ExceptionInterceptor(Prop prop) {
		// TODO Auto-generated constructor stub
		this.prop= prop;
	}
	
	@Override
	public void intercept(Invocation ai) {
		Controller controller=ai.getController();
		try{
			ai.invoke();
		}catch(final Exception e){
    		HttpServletRequest request=controller.getRequest();
    		String ip=IP.getRemoteAddr(request);//ip
    		Integer port=request.getRemotePort();//端口号
    		String uri=request.getRequestURI();//请求uri地址
    		String requestType=request.getContentType();//request请求类型
    		
    		//服务器错误请求日志进mongodb errorLog
    		Map<String, Object> errorMap=errorToMap(e);
    		Record re = new Record()
    		.set("ip",ip)
    		.set("port", port)
    		.set("uri", uri)
    		.set("parameter", getParamMap(request))//将map参数对象写入mongodb
    		.set("request_type", requestType)
    		.set("ctime", new Date())
    		.set("errorMsg",errorMap);
    		
    		//添加错误日志记录到mongodb中
//    		MongoKit.save("errorLog", re);
            
    		//将错误记录到log4j中
    		String logMsg=(String) errorMap.get("msg")+"\n";//错误信息
    		List<String> stList=(List<String>) errorMap.get("stList");//获取堆栈异常集合
    		for(String st:stList){
    			logMsg+="\t"+st+"\n";
    		}
    		log.error(logMsg);
    		
    		//返回异常错误给前端
			Response resp=new Response();
			resp.setErrcode(500);
            controller.renderJson(resp);//返回服务器异常
            
            //打印错误堆栈异常
            e.printStackTrace();
            
            //发送邮件给管理员
            
            Thread t=new Thread(new Runnable() {
				@Override
				public void run() {
					String host=prop.get("email.host");
	                String username=prop.get("email.username");
	                String password=prop.get("email.password");
	                String[] tos=prop.get("email.tousers").split(",");
	                MailSendHelper sendHelper = new MailSendHelper(host, username, password, true);
	                String msg=formatEceptionMsg(e);
	                try {
	    				Boolean b = sendHelper.sendHtmlMail(tos, null, null, "reman系统错误信息", msg, null);
	    			} catch (Exception e1) {
	    				e1.printStackTrace();
	    			}
				}
			});
            t.start();
            
		}
	}

	/**
	 * 格式化异常信息
	 * @param e
	 * @return
	 */
	public String formatEceptionMsg(Exception e){
    	String str="<html><head></head><body>";
 		str+="时间:"+DateUtil.formatDate(new Date())+"<br>";
    	StackTraceElement [] messages=e.getStackTrace();
		StackTraceElement element=null;
		str+=e.getClass().getName()+"<br />";
		for(int i=0,length=messages.length;i<length;i++){
			element=messages[i];
			String className=element.getClassName();
			if(className.startsWith("com.manage.app")){
				str+="<font style='color:red;'>";				
			}else{				
				str+="<font>";
			}
			str+="at "+element.getClassName()+"."
			+element.getMethodName()
			+"("+element.getFileName()
			+":"+element.getLineNumber()+")";
			str+="</font>";
		    str+="<br />";
		}
		str+="</body></html>";
		return str;
    }
	
	/**
	 * 将异常信息转为map对象
	 * @param e
	 * @return
	 */
	public Map<String, Object> errorToMap(Exception e){
		List<String> errorList=new ArrayList<String>();
		errorList.add(e.getClass().getName());//引起错误的类
    	StackTraceElement [] messages=e.getStackTrace();
		StackTraceElement element=null;
		for(int i=0,length=messages.length;i<length;i++){
			element=messages[i];
			String className=element.getClassName();
			String methodName=element.getMethodName();
			String fileName=element.getFileName();
			String errorLineNumber=element.getLineNumber()+"";
			String msg="at "+className+"."+methodName+"("+fileName+":"+errorLineNumber+")";
			errorList.add(msg);
		}
		Map<String, Object> map=new HashMap<String, Object>();
		map.put("msg", e.getMessage());//错误消息
		map.put("stList", errorList);//堆栈错误集合
		return map;
    }
	
	/**
	 * 获取参数的集合
	 * @param request
	 * @return 参数的集合
	 */
	private Map<String, Object> getParamMap(HttpServletRequest request) {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		Enumeration<String> paramNames = request.getParameterNames();
		String paramName = "";
		String paramValue = "";
		while (paramNames.hasMoreElements()) {
			paramName = paramNames.nextElement();
			paramValue = request.getParameter(paramName);
			//如果参数名带“.”则替换为下划线“_”
			paramName=paramName.replace(".", "_");
			paramMap.put(paramName, paramValue);
		}
		return paramMap;
	}
	public static void main(String[] args) {
		String host="smtp.163.com";
        String username="hbxhsys@163.com";
        String password="zhushunfu";
        String[] tos=new String[]{"335089403@qq.com"};
        String msg="test";
        MailSendHelper sendHelper = new MailSendHelper(host, username, password, true);
        try {
        	Boolean b = sendHelper.sendHtmlMail(tos, null, null, "reman系统错误信息", msg, null);
			System.out.println(b);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
	
}
